<template>
  <DataGrid
    ref="table"
    :data="tableData"
    :striped="options.stripe"
    :selectionMode="options.selectMode"
    @selectionChange="onSelectChange"
    :loading="loading"
    :loadMsg="options.loadingText"
    :multiSort="true"
    :columnResizing="true"
    v-bind="options.attributes"
    v-on="options.events"
  >
    <GridColumn
      v-if="options.selectMode === SelectMode.MULTIPLE_CHECKBOX_ROWS"
      align="center"
      :width="50"
    >
      <template v-slot:header>
        <CheckBox
          v-model="tableCheckedAll"
          @checkedChange="onAllCheckedChange($event)"
        ></CheckBox>
      </template>

      <template v-slot:body="scope">
        <CheckBox
          v-model="scope.row.selected"
        ></CheckBox>
      </template>
    </GridColumn>

    <GridColumn
      v-if="options.rowNumber"
      cellCss="datagrid-td-rownumber"
      align="center"
      :width="30"
    >
      <template v-slot:body="slotProps">
        {{ rowNumber(slotProps.rowIndex) }}
      </template>
    </GridColumn>

    <template v-for="column of options.columns" :key="column.prop">
      <GridColumn
        :hidden="!columnShow(column)"
        :title="column.label ? column.label : column.prop"
        :field="column.prop"
        :width="column.width"
        :align="column.align ? column.align : Align.LEFT"
        :sortable="true"
        v-bind="column.attributes ? column.attributes : {}"
        v-on="column.events ? column.events : {}"
      >
        <template #body="slotProps">
          <slot
            :name="'column-' + column.prop"
            :row="slotProps.row"
            :column="slotProps.column"
            :rowIndex="slotProps.rowIndex"
            :value="slotProps.row[column.prop]"
          >{{ slotProps.row[column.prop] }}
          </slot>
        </template>
      </GridColumn>
    </template>
  </DataGrid>
</template>

<script setup lang="ts">
import {computed, onBeforeMount, onBeforeUnmount, PropType, ref, watch,} from "vue";
import _ from "lodash";
import ArkTableOptionsDefault, {
  Align,
  ArkTableExpose,
  type ArkTableOptions,
  Column,
  PaginationData,
  SelectMode
} from "./ArkTableOptions.ts";

/** 组合（向选项里合并 property）。包括：provide、inject、extends、mixins */

/** 接口（组件的接口）。包括：defineOptions、defineModel、defineProps、defineEmits、defineExpose、defineSlots */
const options = defineModel("options", {
  type: Object as PropType<ArkTableOptions<any>>,
  default: () => ArkTableOptionsDefault
});

defineExpose<ArkTableExpose>({
  fetchData() {
    return fetchData();
  },
});

/** 本地状态 (本地的响应式 property)。包括：ref、computed */
// 表格数据
const tableData = computed(() => {
  const data = options.value.data;
  if (_.isNil(data)) {
    return [];
  }
  return data.map((item) => item);
});

// 选择相关
const isSingleSelectMode = computed(() => {
  const selectMode: SelectMode = options.value?.selectMode;
  return [SelectMode.SINGLE_ROW, SelectMode.SINGLE_CELL].includes(selectMode);

})
const isRowSelectMode = computed(() => {
  const selectMode: SelectMode = options.value?.selectMode;
  return [SelectMode.SINGLE_ROW, SelectMode.MULTIPLE_ROWS, SelectMode.MULTIPLE_CHECKBOX_ROWS].includes(selectMode);

})
const tableSelectedRowData = computed(() => {
  if (_.isNil(options.value.data)) {
    return []
  }

  return options.value.data.filter((row) => {
    return row.selected;
  });
});
const tableSelectedCellData = ref<{
  column: Column,
  row: T,
}[]>([])
const tableCheckedAll = computed(() => {
  return (
    options.value.selectData.length !== 0 &&
    options.value.selectData.length === options.value.data.length
  );
});

// 加载中...
const loading = ref(false);

/** 事件（通过响应式事件触发的回调）。包括：watch */
watch(
  () => {
    return tableSelectedRowData.value
  },
  (newVal) => {
    options.value.selectData = newVal
  }
)
watch(
  () => {
    return tableSelectedCellData.value
  },
  (newVal) => {
    options.value.selectData = newVal
  },
  {deep: true}
)

/** 生命周期钩子（按照它们被调用的顺序）。包括：onBeforeMount、onMounted、onBeforeUpdate、onUpdated、onBeforeUnmount、onUnmounted */
onBeforeMount(() => {
  init();
});
onBeforeUnmount(() => {
  options.value.selectData = [];
});

/** 非响应式的 property（不依赖响应系统的实例 property）。包括：常规函数 */
const init = () => {
  _.defaultsDeep(options.value, ArkTableOptionsDefault);

  // 手动抓取数据
  if (!options.value.manualFetchData) {
    fetchData();
  }
};
const fetchData = () => {
  const defineDataFetch = options.value.defineDataFetch;

  if (_.isNil(defineDataFetch)) {
    return Promise.resolve();
  }

  loading.value = true;
  const fetchResult = defineDataFetch({
    ...options.value.fetchDataParams,
    pageSize: options.value.pagination?.pageSize,
    pageNumber: options.value.pagination?.pageNumber,
  });

  // 返回值为Array
  if (Array.isArray(fetchResult)) {
    handleNonPaginationData(fetchResult);

    options.value.selectData = [];
    loading.value = false;

    return Promise.resolve();
  }

  // 返回值为Promise
  if (fetchResult instanceof Promise) {
    return Promise.resolve(fetchResult)
      .then((promiseReturnVal) => {
        if (Array.isArray(promiseReturnVal)) {
          handleNonPaginationData(promiseReturnVal);
          return;
        }

        handlePaginationData(promiseReturnVal);
      })
      .finally(() => {
        options.value.selectData = [];
        loading.value = false;
      });
  }

  // 返回值为PaginationData
  handlePaginationData(fetchResult);

  options.value.selectData = [];
  loading.value = false;

  return Promise.resolve();
};
const handleNonPaginationData = (data) => {
  options.value.data = data;
  options.value.pagination.pageNumber = 1;
  options.value.pagination.total = data.length;
};
const handlePaginationData = (paginationData: PaginationData<any>) => {
  options.value.data = paginationData.rows;

  const maxPageNumber =
    paginationData.total > 0
      ? Math.ceil(paginationData.total / paginationData.pageSize)
      : 1;
  const pageNumber = options.value.pagination.pageNumber;
  if (pageNumber !== undefined) {
    if (pageNumber > maxPageNumber && paginationData.rows?.length === 0) {
      options.value.pagination.pageNumber = maxPageNumber;
    }
  }

  options.value.pagination.total = paginationData.total;
};

const columnShow = (column: Column) => {
  if (!_.isNil(column.show)) {
    return column.show;
  }
  return true;
};

const rowNumber = (rowIndex: number) => {
  if (!options.value.pagination || options.value.rowNumberPageStart) {
    return rowIndex + 1;
  }

  const pageNumber = options.value.pagination.pageNumber;
  const pageSize = options.value.pagination.pageSize;

  if (pageNumber === 1) {
    return rowIndex + 1;
  }

  return (pageNumber - 1) * pageSize + (rowIndex + 1);
};

const onSelectChange = (e) => {
  const selectMode: SelectMode = options.value.selectMode;

  if (selectMode === SelectMode.NONE) {
    return;
  }

  // 若是single选择模式，则e对象包装成数组
  if (isSingleSelectMode.value) {
    e = [e]
  }

  // 若是row选择模式，则维护options.value.data的selected属性
  // 为SelectMode.MULTIPLE_CHECKBOX_ROWS模式的全选功能做准备
  if (isRowSelectMode.value) {
    options.value.data.forEach((item) => {
      const index = _.findKey(e, (value) => {
        return value === item;
      });

      if (_.isNil(index)) {
        item.selected = false
        return;
      }

      item.selected = true
    });

    return;
  }

  tableSelectedCellData.value = e
};
const onAllCheckedChange = (checked) => {
  options.value.data.forEach((row) => {
    row.selected = checked;
  });
};

/** 其它 */
</script>

<style scoped lang="scss">
:deep(.panel-body) {
  border-top-color: rgba(0, 0, 0, 0.2) !important;
  border-bottom: none;
}
</style>
